package com.fuchuang.seckillsystem.controller;

import com.fuchuang.seckillsystem.config.DroolsConfig;
import com.fuchuang.seckillsystem.dto.KeyConstants;
import com.fuchuang.seckillsystem.exception.GlobalException;
import com.fuchuang.seckillsystem.mapper.OverRecordMapper;
import com.fuchuang.seckillsystem.utils.JsonWebTokenUtils;
import com.fuchuang.seckillsystem.utils.Sm4Utils;
import com.fuchuang.seckillsystem.vo.LoginToken;
import com.fuchuang.seckillsystem.vo.RespBean;
import com.fuchuang.seckillsystem.vo.RespBeanEnum;
import org.kie.api.KieBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Set;

@RestController
public class CommonController {
    
    @Autowired
    private JsonWebTokenUtils jsonWebTokenUtils;
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private Sm4Utils sm4Utils;
    
    @Resource
    private OverRecordMapper overRecordMapper;
    
    /**
     * 刷新令牌
     */
    @PostMapping("refreshToken")
    public RespBean refreshToken(HttpServletRequest request) {
        //从请求头中获取refreshToken
        String oldRefreshToken = request.getHeader("refreshToken");
        //校验refreshToken，如果令牌过期
        if (jsonWebTokenUtils.isTokenExpired(oldRefreshToken)) {
            return RespBean.error(RespBeanEnum.TOKEN_EXPIRED_ERROR);
        }
        //oldRefreshToken
        String username = jsonWebTokenUtils.getUsernameFromToken(oldRefreshToken);
        //生成新的Token
        String token = jsonWebTokenUtils.generateToken(username);
        String refreshToken = jsonWebTokenUtils.getNewRefreshToken(oldRefreshToken);
        Date expireTime = new Date(System.currentTimeMillis() + jsonWebTokenUtils.getExpiration() - 1000);
        LoginToken loginToken = new LoginToken(token, refreshToken, expireTime);
        return RespBean.success(loginToken);
    }
    
    /**
     * 修改服务器规则文件后，访问该接口刷新内存中的规则
     */
    @PostMapping("/refreshConfig")
    @PreAuthorize("hasAnyRole('ROLE_ADMIN')")
    public RespBean reloadInstance() {
        //获取上下文
        DefaultListableBeanFactory defaultListableBeanFactory =
                (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        KieBase result = (KieBase) defaultListableBeanFactory.getBean("kieBase");
        //销毁指定实例 execute是上文注解过的实例名称
        defaultListableBeanFactory.destroySingleton("kieBase");
        //按照旧有的逻辑重新获取实例,Excute是我自己逻辑中的类
        try {
            KieBase kieBase = DroolsConfig.getKieBase();
            //重新注册同名实例，这样在其他地方注入的实例还是同一个名称，但是实例内容已经重新加载
            defaultListableBeanFactory.registerSingleton("kieBase", kieBase);
            //删除redis中缓存的规则
            redisTemplate.delete(KeyConstants.RECORD_QUERY);
            //删除redis中登录用户数据
            Set<String> keys = redisTemplate.keys(KeyConstants.USER_DETAIL + "*");
            if (keys != null && keys.size() > 0) {
                redisTemplate.delete(keys);
            }
        } catch (Exception e) {
            //如果重新注入失败
            defaultListableBeanFactory.registerSingleton("kieBase", result);
            throw new GlobalException(RespBeanEnum.UPDATE_ERROR);
        }
        return RespBean.success();
    }
    
}
